package com.zf.nio.async;

import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.Future;

/**
 * 在 Java 7 中，Java NIO 中添加了 AsynchronousFileChannel，也就是是异步地将数
 * 据写入文件。
 * @author Zhou Feng
 */
public class AsynchronousFileChannelDemo01 {


    /**
     * 使用Feature方式读取数据
     */
    @Test
    public void read1(){
        Path path = Paths.get("d:\\a.txt");
        AsynchronousFileChannel fileChannel = null;
        try {
            fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
        } catch (
                IOException e) {
            e.printStackTrace();
        }
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        long position = 0;
        Future<Integer> operation = fileChannel.read(buffer, position);
        while(!operation.isDone());
        buffer.flip();
        byte[] data = new byte[buffer.limit()];
        buffer.get(data);
        System.out.println(new String(data));
        buffer.clear();
    }


    /**
     * 使用 回调读取数据
     */
    @Test
    public void read2(){
        Path path = Paths.get("d:\\a.txt");
        AsynchronousFileChannel fileChannel = null;
        try {
            fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        long position = 0;
        fileChannel.read(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() {
            /**
             * 读取操作完成，将调用 CompletionHandler 的 completed()方法
             * @param result 读取了多少字节
             * @param attachment  read()方法的第三个参数, 本例中是 buffer
             */
            @Override
            public void completed(Integer result, ByteBuffer attachment) {
                System.out.println("result = " + result);
                attachment.flip();
                byte[] data = new byte[attachment.limit()];
                attachment.get(data);
                System.out.println(new String(data));
                attachment.clear();
            }

            /**
             * 如果读取操作失败，则将调用 CompletionHandler 的 failed()方
             */
            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
            }
        });
    }

    /**
     * 通过feature方式写数据
     */
    @Test
    public void write1() throws IOException {
        Path path = Paths.get("d:\\b.txt");
        if (!Files.exists(path)){
            Files.createFile(path);
        }

        AsynchronousFileChannel fileChannel = null;
        try {
            fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        long position = 0;
        buffer.put("atguigu data".getBytes());
        buffer.flip();
        Future<Integer> operation = fileChannel.write(buffer, position);
        buffer.clear();
        while(!operation.isDone());
        System.out.println("Write over");

    }


    /**
     * 通过回调方式写数据
     * 当写操作完成时，将会调用 CompletionHandler 的 completed()方法。如果写失败，
     * 则会调用 failed()方法。
     */
    @Test
    public void write2() throws IOException {
        Path path = Paths.get("d:\\b.txt");
        if(!Files.exists(path)){
            Files.createFile(path);
        }
        AsynchronousFileChannel fileChannel = null;
        try {
            fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        long position = 0;
        buffer.put("atguigu data".getBytes());
        buffer.flip();
        fileChannel.write(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() {
            @Override
            public void completed(Integer result, ByteBuffer attachment) {
                System.out.println("bytes written: " + result);
            }
            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
                System.out.println("Write failed");
                exc.printStackTrace();
            }
        });

    }

}
